package com.jt.www.admin.pay.service.impl;

import com.alibaba.fastjson.JSON;
import com.jt.www.admin.pay.service.PayStateService;
import com.jt.www.dao.mapper.woxuebao.PayRecordEntityMapper;
import com.jt.www.enums.ResultEnum;
import com.jt.www.enums.issue.AppStatusEnum;
import com.jt.www.enums.issue.PayChannelEnum;
import com.jt.www.enums.woxuebao.HandlerStatusEnum;
import com.jt.www.enums.woxuebao.PayRecordHandlerStatusEnum;
import com.jt.www.model.pay.StatusRecordVO;
import com.jt.www.model.remote.ins.InsManagerResultVO;
import com.jt.www.model.reps.GenericDataResponse;
import com.jt.www.model.reps.ResponseData;
import com.jt.www.model.reps.ResultDTO;
import com.jt.www.model.vo.InsManagerQo;
import com.jt.www.model.woxuebao.PayRecordEntity;
import com.jt.www.model.woxuebao.PayStateDTO;
import com.jt.www.model.woxuebao.TOrderChargeQueryVO;
import com.jt.www.remote.ins.InsClient;
import com.jt.www.remote.woxuebao.InsOrderClient;
import com.jt.www.util.DateUtils;
import com.jt.www.util.JsonUtils;
import org.apache.commons.lang.StringUtils;
import org.assertj.core.util.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;

/**
 * @author admin_ltf
 * @create 2019-06-03 19:19
 */
@Service
public class PayStateServiceImpl implements PayStateService {

    public static final Logger log = LoggerFactory.getLogger(PayStateServiceImpl.class);
    private static final int PAY_TRY_TIMES = 3;
    @Autowired
    PayRecordEntityMapper payRecordEntityMapper;
    @Autowired
    InsOrderClient insOrderClient;
    @Autowired
    InsClient insClient;

    public ResultDTO changePayState(PayStateDTO payStateDTO) throws Exception {

        log.info(DateUtils.getCurrentTime() + ",开始调用投保平台支付接口，，，");
        // 首先入库

        // 经过测试，沟通，发现 一条消息 可能会发送多次，需要这边 再处理一次：排重。根据orderSubNo处理
        // 7.10 号  逻辑变了
        String orderSubNo = payStateDTO.getOrderSubNo();
        PayRecordEntity payRecordEntity = new PayRecordEntity();
        String orderNo = null;
        if (StringUtils.isEmpty(orderSubNo)) {

            orderNo = payStateDTO.getOrderNo();
            payRecordEntity.setOrderno(orderNo);
        } else {
            payRecordEntity.setOrdersubno(orderSubNo);
        }
        payRecordEntity.setHandlestatus(PayRecordHandlerStatusEnum.YES.getCode());
        List<PayRecordEntity> list = payRecordEntityMapper.select(payRecordEntity);
        if (list == null || list.size() == 0) {
            payRecordEntity = new PayRecordEntity();
            payRecordEntity.setOrdersubno(payStateDTO.getOrderSubNo());
            payRecordEntity.setTradeno(payStateDTO.getTradeNo());
            String payEndTime = payStateDTO.getPayEndTime();
            payRecordEntity.setPayendtime(payEndTime);
            payRecordEntity.setOrderno(payStateDTO.getOrderNo());
            payRecordEntity.setPaychannel(payStateDTO.getPayChannel());
            String statusStr = payStateDTO.getStatus();
            Integer status = null;
            if (!StringUtils.isEmpty(statusStr)) {
                status = Integer.valueOf(statusStr);
            }
            payRecordEntity.setHandlestatus(PayRecordHandlerStatusEnum.DEFAULT.getCode());
            payRecordEntity.setStatus(status);
            payRecordEntity.setIsDeleted(false);
            int num = payRecordEntityMapper.insert(payRecordEntity);
            Long id = null;
            if (num == 1) {
                id = payRecordEntity.getId();
            }

//        try {
            String code = sendPayStatus(payStateDTO);
            if ("0000".equals(code)) {
                // 修改状态
                payRecordEntity = new PayRecordEntity();
                payRecordEntity.setId(id);
                payRecordEntity.setHandlestatus(PayRecordHandlerStatusEnum.YES.getCode());
                num = payRecordEntityMapper.updateByPrimaryKeySelective(payRecordEntity);
                if (num > 0) {
                    return new ResultDTO(ResultEnum.PAY_SUCCESS, "成功");
                }

            } else if ("9999".equals(code)) {
                // 修改状态
                payRecordEntity = new PayRecordEntity();
                payRecordEntity.setId(id);
                payRecordEntity.setHandlestatus(PayRecordHandlerStatusEnum.NO.getCode());
                num = payRecordEntityMapper.updateByPrimaryKeySelective(payRecordEntity);
                if (num > 0) {
                    return new ResultDTO(ResultEnum.PAY_SUCCESS, "成功");
                }
            } else {
                // 修改状态
                payRecordEntity = new PayRecordEntity();
                payRecordEntity.setId(id);
                payRecordEntity.setHandlestatus(HandlerStatusEnum.OVER.getCode());
                num = payRecordEntityMapper.updateByPrimaryKeySelective(payRecordEntity);
                if (num > 0) {
                    return new ResultDTO(ResultEnum.PAY_SUCCESS, "成功");
                }
            }

        } else {
            log.info("订单号orderSubNo是" + orderNo + "的消息已经被处理，不能重复处理");
        }

        return new ResultDTO(ResultEnum.PAY_SUCCESS, "请求成功");
    }


    // 领导要求加一个 请求超时的判断
    private String sendPayStatus(PayStateDTO payStateDTO) throws Exception {
        //往投保平台传值的时候需要重新拼对象
        TOrderChargeQueryVO tOrderChargeQueryVO = new TOrderChargeQueryVO();
        String orderSubNo = payStateDTO.getOrderSubNo();
        tOrderChargeQueryVO.setApplicationFormCode(orderSubNo);
        tOrderChargeQueryVO.setChargeNo(payStateDTO.getTradeNo());
        tOrderChargeQueryVO.setConfirmDate(payStateDTO.getPayEndTime());
        if (StringUtils.isEmpty(orderSubNo)) {
            tOrderChargeQueryVO.setOrderCode(payStateDTO.getOrderNo());
        }
        //转换支付对应的支付channel及code
        tOrderChargeQueryVO.setPayChannel(PayChannelEnum.getCodeByChannel(payStateDTO.getPayChannel()));

        log.info("参数：" + JsonUtils.toJson(tOrderChargeQueryVO));
        tOrderChargeQueryVO.setStatus(payStateDTO.getStatus());

        //在支付过程中，有可能已经支付超时定时任务已经将投保中心的投保单状态修改成11(失效)，在这里检查并修正 回来
        checkAndProcessAppStatus(tOrderChargeQueryVO);

        ResponseEntity<GenericDataResponse<Map<String, String>>> genericDataResponseResponseEntity = null;
        int times = 0;
        while (times++ < PAY_TRY_TIMES && null == (genericDataResponseResponseEntity = insOrderClient.orderPay(tOrderChargeQueryVO))) {
            log.info("投保单号：{}，定单号：{}调用投保平台支付接口失败第{}次", tOrderChargeQueryVO.getApplicationFormCode(), tOrderChargeQueryVO.getOrderCode(), times);
            Thread.sleep(200);
        }
        log.info("投保单号：{}，定单号：{}调用投保平台支付接口结束，结果：{}", tOrderChargeQueryVO.getApplicationFormCode(), tOrderChargeQueryVO.getOrderCode(), genericDataResponseResponseEntity);
        if (genericDataResponseResponseEntity != null) {
            GenericDataResponse<Map<String, String>> body = genericDataResponseResponseEntity.getBody();
            String code = body.getCode();
            log.info("调用投保平台支付接口响应码:{},消息:{}", code, body.getMsg());
            return code;
        } else {
            return null;
        }
    }

    /**
     * 在支付过程中，有可能已经支付超时定时任务已经将投保中心的投保单状态修改成11(失效)，在这里检查并修正 回来
     *
     * @param tOrderChargeQueryVO
     */
    private void checkAndProcessAppStatus(TOrderChargeQueryVO tOrderChargeQueryVO) {
        InsManagerQo insManagerQo = new InsManagerQo();
        insManagerQo.setOrderCode(tOrderChargeQueryVO.getOrderCode());
        insManagerQo.setAppCode(tOrderChargeQueryVO.getApplicationFormCode());
        insManagerQo.setChannelCode("edu");
        insManagerQo.setChannelType("02");

        try {
            ResponseData rets = insClient.searchManagerAppList(JSON.toJSONString(insManagerQo));
            //判断  网络异常
            if (null == rets || null == rets.getList()) {
                return;
            }
            //投保中心返回的结果集
            List<InsManagerResultVO> list = (List<InsManagerResultVO>) rets.getList();
            list = JSON.parseArray(JSON.toJSONString(list), InsManagerResultVO.class);
            if (!CollectionUtils.isEmpty(list)) {
                //需要修改的集合
                List<StatusRecordVO> statusRecordVOs = Lists.newArrayList();
                //判断 投保单支付状态
                for (InsManagerResultVO insManagerResultVO : list) {
                    //如果已经因为支付超时做了失效，在这里将状态修正回来
                    if (AppStatusEnum.AS_11.getCode().equals(insManagerResultVO.getAppStatus())) {
                        //添加修改状态的集合
                        StatusRecordVO statusRecordVO = new StatusRecordVO();
                        statusRecordVO.setApplicationFormCode(insManagerResultVO.getAppCode());
                        //修改成已取消状态
                        statusRecordVO.setNewStatus(AppStatusEnum.AS_08.getCode());
                        statusRecordVO.setOperator("edu_system");// 当前用户
                        statusRecordVO.setTapplicationFormId(0);
                        statusRecordVO.setType("00");
                        statusRecordVOs.add(statusRecordVO);
                    }
                }
                if (!CollectionUtils.isEmpty(statusRecordVOs)) {
                    //支付超时修改投保中心状态 在这里批量修改回来
                    insClient.updateApplicationStatus(statusRecordVOs);
                }
            }
        } catch (Exception e) {
            log.info("投保中心调用支付校验接口异常");
            throw new RuntimeException(e.getMessage());
        }
    }
}
